/**
 * Copyright 2019 吉鼎科技.

 * <p>
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * <p>
 * http://www.apache.org/licenses/LICENSE-2.0
 * <p>
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package cn.easyplatform.web.task.zkex.list.group;

import cn.easyplatform.lang.Strings;
import cn.easyplatform.messages.vos.datalist.ListHeaderVo;
import cn.easyplatform.messages.vos.datalist.ListVo;
import cn.easyplatform.type.ListRowVo;
import cn.easyplatform.web.task.zkex.ListSupport;
import cn.easyplatform.web.task.support.ExpressionEngine;
import cn.easyplatform.web.task.support.SupportFactory;
import org.zkoss.zk.ui.Component;
import org.zkoss.zul.AbstractTreeModel;

import java.util.ArrayList;
import java.util.List;

/**
 * @author <a href="mailto:davidchen@epclouds.com">littleDog</a> <br/>
 * @since 2.0.0 <br/>
 */
public abstract class TreeModel extends AbstractTreeModel<DefaultTreeNode<ListRowVo>> {

    protected String name;

    protected String title;

    protected int[] fieldIndexs;

    protected String style;

    protected TreeModel child;

    protected TreeModel parent;

    protected int level;

    protected Object[] oldValue;

    protected Object[] oldValues;

    protected List<TotalValue> totalValues;

    protected List<ListHeaderVo> headers;

    protected ExpressionEngine groupEngine;

    protected ListSupport support;

    protected DefaultTreeNode<ListRowVo> rootNode;

    protected int index;

    protected int count;

    public TreeModel(ListSupport support, String[] fields) {
        super(new DefaultTreeNode<ListRowVo>(null));
        this.rootNode = super.getRoot();
        this.support = support;
        ListVo listVo = support.getLayout();
        headers = listVo.getHeaders();
        if (!Strings.isBlank(listVo.getOnGroup()))
            groupEngine = SupportFactory.getExpressionEngine(support,
                    listVo.getOnGroup());
        if (fields.length > 0) {
            this.fieldIndexs = new int[fields.length];
            int index = 0;
            for (int i = 0; i < listVo.getHeaders().size(); i++) {
                ListHeaderVo hv = listVo.getHeaders().get(i);
                for (String f : fields) {
                    if (hv.getName().equals(f)) {
                        this.fieldIndexs[index] = i;
                        index++;
                        break;
                    }
                }
            }
        } else
            this.fieldIndexs = new int[0];
    }

    public DefaultTreeNode<ListRowVo> getRoot() {
        return rootNode;
    }

    public String getName() {
        return name;
    }

    public String getTitle() {
        return title;
    }

    public void addTotal(int totalType, int index) {
        if (totalValues == null)
            totalValues = new ArrayList<TotalValue>();
        totalValues.add(new TotalValue(totalType, index));
        if (child != null)
            child.addTotal(totalType, index);
    }

    void addGroup(TreeModel group) {
        this.child = group;
        this.child.level = level + 1;
        this.child.parent = this;
    }

    public void save() {
        if (oldValue != null) {
            if (oldValues == null)
                oldValues = new Object[oldValue.length];
            for (int i = 0; i < oldValue.length; i++)
                oldValues[i] = oldValue[i];
        }
        if (child != null)
            child.save();
    }

    public void reset() {
        oldValue = null;
        if (child != null)
            child.reset();
    }

    public void reIndex(boolean isDown) {
        index = 0;
        if (isDown) {
            if (child != null)
                child.reIndex(isDown);
        } else if (parent != null)
            parent.reIndex(isDown);
    }

    public void setIndex(boolean isDown) {
        index++;
        count++;
        if (isDown) {
            if (child != null)
                child.setIndex(isDown);
        } else if (parent != null)
            parent.setIndex(isDown);
    }

    public void clear() {
        oldValue = null;
        oldValues = null;
        if (totalValues != null) {
            for (TotalValue gv : totalValues)
                gv.reset();
        }
        if (child != null)
            child.clear();
        index = 0;
        count = 0;
    }


    @Override
    public boolean isLeaf(DefaultTreeNode<ListRowVo> listRowVoDefaultTreeNode) {
        return listRowVoDefaultTreeNode.isLeaf();
    }

    @Override
    public DefaultTreeNode<ListRowVo> getChild(DefaultTreeNode<ListRowVo> listRowVoDefaultTreeNode, int i) {
        return (DefaultTreeNode<ListRowVo>) listRowVoDefaultTreeNode.getChildAt(i);
    }

    @Override
    public int getChildCount(DefaultTreeNode<ListRowVo> listRowVoDefaultTreeNode) {
        return listRowVoDefaultTreeNode.getChildCount();
    }

    public abstract <T extends Component> T createGroup(ResultHelper rh, int showLevel);
}
